package com.hoas.quicklysdk.aliyun.oss;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import com.hoas.quicklysdk.aliyun.oss.configure.AliyunOssProperties;
import com.hoas.quicksdk.api.oss.OssClient;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Calendar;

@Slf4j
public class AliyunOssClient implements OssClient {

    private AliyunOssProperties properties;

    public AliyunOssClient(AliyunOssProperties properties) {
        this.properties = properties;
    }

    @Override
    public boolean simpleUpload(String fileName, InputStream in) {
        return simpleUpload( properties.getBucketName(), fileName, in );
    }

    @Override
    public boolean simpleUpload(String fileName, InputStream in, Long expireTime) {
        return simpleUpload( properties.getBucketName(), fileName, in, expireTime );
    }

    @Override
    public boolean simpleUpload(String fileName, File file) {
        return simpleUpload( properties.getBucketName(), fileName, file );
    }

    @Override
    public boolean simpleUpload(String fileName, File file, Long expireTime) {
        return simpleUpload( properties.getBucketName(), fileName, file, expireTime );
    }

    @Override
    public boolean simpleUpload(String bucketName, String fileName, InputStream in) {
        return simpleUpload( bucketName, fileName, in, null);
    }

    @Override
    public boolean simpleUpload(String bucketName, String fileName, InputStream in, Long expireTime) {

        // 创建OSSClient实例。
        OSS ossClient = createOssClient();

        // <yourObjectName>表示上传文件到OSS时需要指定包含文件后缀在内的完整路径，例如abc/efg/123.jpg。
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, in);

        // 如果需要上传时设置存储类型与访问权限，请参考以下示例代码。
        ObjectMetadata metadata = new ObjectMetadata();
        if (expireTime != null && expireTime > 0) {

            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.SECOND, expireTime.intValue());
            metadata.setExpirationTime( cal.getTime() );

        }


        try {
            // 上传字符串。
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            return true;

        } catch (OSSException oe) {
            log.error("文件上传OSS失败" , oe);
            return false;

        } catch (ClientException ce) {
            log.error("文件上传OSS失败" , ce);

            return false;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }


    }


    @Override
    public boolean simpleUpload(String bucketName, String fileName, File file) {
        return simpleUpload(bucketName, fileName, file, null);
    }

    @Override
    public boolean simpleUpload(String bucketName, String fileName, File file, Long expireTime) {
        // 创建OSSClient实例。
        OSS ossClient = createOssClient();

        // <yourObjectName>表示上传文件到OSS时需要指定包含文件后缀在内的完整路径，例如abc/efg/123.jpg。
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, file);

        // 如果需要上传时设置存储类型与访问权限，请参考以下示例代码。
         ObjectMetadata metadata = new ObjectMetadata();
         if (expireTime != null && expireTime > 0) {

             Calendar cal = Calendar.getInstance();
             cal.add(Calendar.SECOND, expireTime.intValue());
             metadata.setExpirationTime( cal.getTime() );

         }
        // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
        // metadata.setObjectAcl(CannedAccessControlList.Private);
        // putObjectRequest.setMetadata(metadata);


        try {
            // 上传字符串。
            log.info("开始文件上传");
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            return true;

        } catch (OSSException oe) {
            log.error("文件上传OSS失败" , oe);

            return false;

        } catch (ClientException ce) {
            log.error("文件上传OSS失败" , ce);

            return false;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

    }

    @Override
    public boolean uploadBigFile(String bucketName, String fileName, File file) {
        return uploadBigFile(bucketName, fileName, file, null);
    }

    @Override
    public boolean uploadBigFile(String bucketName, String fileName, File file, Long expireTime) {
        // 创建OSSClient实例。
        OSS ossClient = createOssClient();


        // 如果需要上传时设置存储类型与访问权限，请参考以下示例代码。
        ObjectMetadata metadata = new ObjectMetadata();
        // 指定上传的内容类型。
        metadata.setContentType("text/plain");
        if (expireTime != null && expireTime > 0) {

            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.SECOND, expireTime.intValue());
            metadata.setExpirationTime( cal.getTime() );

        }
        // 通过UploadFileRequest设置多个参数。
        UploadFileRequest uploadFileRequest = new UploadFileRequest(bucketName,fileName);

        // 通过UploadFileRequest设置单个参数。
        // 设置存储空间名称。
        //uploadFileRequest.setBucketName("<yourBucketName>");
        // 指定上传的本地文件。
        uploadFileRequest.setUploadFile(file.getAbsolutePath());
        // 指定上传并发线程数，默认为1。
        uploadFileRequest.setTaskNum(5);
        // 指定上传的分片大小。
        uploadFileRequest.setPartSize(1 * 1024 * 1024);
        // 开启断点续传，默认关闭。
        uploadFileRequest.setEnableCheckpoint(true);
        // 记录本地分片上传结果的文件。
        uploadFileRequest.setCheckpointFile(properties.getCheckpointFile());
        // 文件的元数据。
        uploadFileRequest.setObjectMetadata(metadata);
        // 设置上传成功回调，参数为Callback类型。


        // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
        // metadata.setObjectAcl(CannedAccessControlList.Private);
        // putObjectRequest.setMetadata(metadata);


        try {
            // 上传字符串。
            log.info("开始文件上传");
            // 断点续传上传。
            ossClient.uploadFile(uploadFileRequest);
            return true;

        } catch (OSSException oe) {
            log.error("文件上传OSS失败" , oe);

            return false;

        } catch (ClientException ce) {
            log.error("文件上传OSS失败" , ce);

            return false;
        } catch (Throwable e) {
            log.error("文件上传OSS失败" , e);

            return false;

        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

    }



    @Override
    public InputStreamReader simpleDownload2InputStream(String bucketName, String fileName) {

        // 创建OSSClient实例。
        OSS ossClient = createOssClient();

        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
        OSSObject ossObject = ossClient.getObject(bucketName, fileName);
        return new InputStreamReader(ossObject.getObjectContent());

    }

    @Override
    public String getViewPath(String fileName) {
        return properties.getViewPath() + "/" + fileName;
    }
    @Override
    public String getVideoSnapshotUri(String resourceUrl, int width, int height) {
        return String.format(resourceUrl + "?x-oss-process=video/snapshot,t_%d,f_jpg,w_%d,h_%d,m_fast",0, width, height);
    }


    private OSS createOssClient() {
        OSS ossClient = new OSSClientBuilder().build(properties.getEndpoint(), properties.getAccessKeyId(), properties.getAccessKeySecret());
        return ossClient;
    }

}
